﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

using Domain.DomainBase;

namespace Host.DataTransfer
{
    public static class Transfer
    {
        /// <summary>
        /// 转换为DTO对象
        /// </summary>
        /// <typeparam name="T">DTO类型</typeparam>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public static T ToDTO<T>(this IDomainEntity entity) where T : class
        {
            Type type = typeof(T);
            T result = Activator.CreateInstance(type) as T;
            if (result != null)
            {
                foreach (PropertyInfo item in type.GetProperties())
                {

                    foreach (PropertyInfo property in entity.GetType().GetProperties())
                    {
                        if (property.GetValue(entity, null) == null)
                        {
                            continue;
                        }

                        if (property.Name == item.Name)
                        {
                            object value = property.GetValue(entity, null);
                            item.SetValue(result, value, null);
                            continue;
                        }
                        if (property.Name.StartsWith("Current"))
                        {
                            string propertyName = property.Name.Replace("Current", "") + "ID";
                            if (item.Name == propertyName)
                            {
                                object obj = property.GetValue(entity, null);
                                PropertyInfo objProperty = property.PropertyType.GetProperty(propertyName);
                                object value = objProperty.GetValue(obj, null);
                                item.SetValue(result, value, null);
                            }
                        }

                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 实体转换
        /// </summary>
        /// <remarks>
        /// 用于新建对象
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static T ToModel<T>(this IDomainEntity entity, IList<Func<IDomainEntity>> refEntitie) where T : class
        {
            IEnumerable<IDomainEntity> entityList = refEntitie.Select(li => li());

            Type type = typeof(T);
            T result = Activator.CreateInstance(type) as T;
            foreach (PropertyInfo item in type.GetProperties())
            {
                if (IsBaseData(item))
                {
                    continue;
                }
                foreach (PropertyInfo property in entity.GetType().GetProperties())
                {
                    if (property.Name == item.Name)
                    {
                        item.SetValue(result, property.GetValue(entity, null), null);
                        continue;
                    }
                    if (item.Name.StartsWith("Current"))
                    {
                        string propertyName = item.Name.Replace("Current", "") + "ID";
                        if (property.Name == propertyName)
                        {
                            foreach (IDomainEntity refEntity in entityList)
                            {
                                if (refEntity.GetType() == item.PropertyType)
                                {
                                    item.SetValue(result, refEntity, null);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }

        private static bool IsBaseData(PropertyInfo propertyName)
        {
            if (propertyName.Name == "CreateTime" || propertyName.Name == "CreateUser"
                || propertyName.Name == "EditTime" || propertyName.Name == "EditUser"
                || propertyName.Name == "PassUser" || propertyName.Name == "PassTime"
                || propertyName.Name == "Version" || propertyName.Name == "IsPassed")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static T ToModel<T>(this IDomainEntity entity, Func<T> func, IList<Func<IDomainEntity>> refEntitie) where T : class
        {
            if (func == null) throw new ArgumentNullException("func");

            IEnumerable<IDomainEntity> entityList = refEntitie.Select(li => li());

            Type type = typeof(T);
            T result = func();
            foreach (PropertyInfo item in type.GetProperties())
            {
                if (IsBaseData(item))
                {
                    continue;
                }

                foreach (PropertyInfo property in entity.GetType().GetProperties())
                {
                    if (property.Name == item.Name)
                    {
                        item.SetValue(result, property.GetValue(entity, null), null);
                        continue;
                    }
                    if (item.Name.StartsWith("Current"))
                    {
                        string propertyName = item.Name.Replace("Current", "") + "ID";
                        if (property.Name == propertyName)
                        {
                            foreach (IDomainEntity refEntity in entityList)
                            {
                                if (refEntity.GetType() == item.PropertyType)
                                {
                                    item.SetValue(result, refEntity, null);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }
    }
}
